import { LegalProperties } from "@/constant";
import { IDatabase } from "@/types";
import { replaceTemplateString } from "@/util";
import { ErrorReason } from './constant';


function combineConfigs(targetJson, templateJson) {
    const combined: Record<string, any> = {};
    for (const key in targetJson) {
        if (templateJson[key]) {
            const templateType = Object.prototype.toString.call(templateJson[key]);
            const targetType = Object.prototype.toString.call(targetJson[key]);
            // 如果是对象，需要合并属性
            if (templateType.includes('Object')) {
                if (targetType.includes('Object')) {
                    combined[key] = combineConfigs(targetJson[key], templateJson[key]);
                } else combined[key] = templateJson[key];
            }
            // 如果是数组，以 target 为主
            else if (templateType.includes('Array')) {
                if (targetType.includes('Array')) {
                    combined[key] = [...targetJson[key]];
                } else combined[key] = templateJson[key];
            } else combined[key] = targetJson[key];
            // 如果是其它类型或者是 targetJson 独有的属性，以 targetJson 的为主
      } else combined[key] = targetJson[key];
    }
    // 补充 templateJson 中的信息
    for (const key in templateJson) {
        if (combined[key] === undefined) {
            combined[key] = templateJson[key];
        }
    }
    return combined;
}

/**
 * @description 验证参数存在性
 * @param params 
 * @param includeKeys 
 * @returns 
 */
function paramsValidater<P extends Record<string, any>, V extends string[]>(
    params: P,
    validatedKeys: V,
): [ result: boolean, keyName: string ] {
    for(const key of validatedKeys) {
        const value = params[key];
        if (!value) return [ false, key ]
    }
    return [ true, '' ];
};

/**
 * @description 验证 config 是否合法
 * @param config 
 */
function checkConfig (config: IDatabase) {

    /** 确保必要参数是存在的 */
    const [ isLegal, keyName ] = paramsValidater(config, [ "name", "username", "password", "ip", "table" ])
    if (!isLegal) throw replaceTemplateString(ErrorReason.DataBase.MissingDataBaseProps, keyName);
    
    const { table: confgiTable } = config;

    if (!Array.isArray(confgiTable)) throw replaceTemplateString(ErrorReason.DataBase.MissingDataBaseProps, 'table');

    confgiTable.forEach((table, index) => {
        const { needDefaultProps } = table;
        const [ isLegal, keyName ] = paramsValidater(table, [ "name", "columns" ])
        if (!isLegal) throw replaceTemplateString(ErrorReason.DataBase.MissingIndex, [`${index + 1}`, 'table', keyName]);

        let autoIncrementNums = 0;
        table.columns.forEach((col, _index) => {
            /** 确保必要参数是存在的 */
            const [ isLegal, keyName ] = paramsValidater(col, [ "name", "type" ])
            if (!isLegal) throw replaceTemplateString(ErrorReason.DataBase.MissingIndex, [`${_index + 1}`, `column in table${table.name}`, keyName]);

            /** 确保 column 中定义的属性都是合法的 */
            Object.keys(col).forEach((prop: string) => {
                if (!LegalProperties.includes(prop)) throw replaceTemplateString(ErrorReason.DataBase.BadColumnType);
            })

            /** 如果字段属性为 VARCHAR, 需要指明大小 */
            if (col.type === 'VARCHAR' && !col.charSize) throw replaceTemplateString(ErrorReason.DataBase.CharNeedSize);
           
            if (col.autoIncrement) autoIncrementNums++;
        })
        /** 确保如果需要 id、create_at 等默认属性, 则 autoIncrease 属性不能有, 否则至多只能出现一次 */
        if (
            (needDefaultProps && autoIncrementNums) ||
            autoIncrementNums > 1
        ) throw replaceTemplateString(ErrorReason.DataBase.PropsExceeded, 'autoIncrement');
    })
};

export {
    combineConfigs,
    paramsValidater,
    checkConfig,
}